home *** CD-ROM | disk | FTP | other *** search
- Path: news.mcs.net!usenet
- From: mikey@mcs.com (Mike Young)
- Newsgroups: comp.lang.ada,comp.lang.c++
- Subject: Re: some questions re. Ada/GNAT from a C++/GCC user
- Date: 31 Mar 1996 09:28:09 GMT
- Organization: Fen Software, Inc.
- Message-ID: <4jlj79$h1k@Nntp1.mcs.net>
- References: <wnewmanDoxrCp.DKv@netcom.com> <Dp1oAw.7Cz@world.std.com>
- NNTP-Posting-Host: mikey.pr.mcs.net
- Mime-Version: 1.0
- Content-Type: Text/Plain; charset=US-ASCII
- X-Newsreader: WinVN 0.99.6
-
- In article <Dp1oAw.7Cz@world.std.com>, bobduff@world.std.com says...
- >
- >In article <wnewmanDoxrCp.DKv@netcom.com>,
- >Bill Newman <wnewman@netcom.com> wrote:
- >
- >>...Is there any way of
- >> doing something like this in Ada? (I imagine there is, since the
- >> alternatives look unnecessarily difficult to maintain.)
- >
- >I'll note that the alternatives I gave could be done in C++, too,
- >without macros.
-
- ===========
- If you're interested, the STL in C++ can do precisely this.
-
- template <class T, class S>
- class SumOf
- {
- public:
- SumOf(S initial) : sum(initial);
- void operator()(const T& t) { sum += t; } // T must be convertable to
- // formal type S.
- operator const S&()const { return sum; } // SumOf<T,S> is itself
- // convertable to type S.
- };
-
- typedef list<Stuff> Basket;
- unsigned BasketTotal(const Basket & basket)
- {
- SumOf<Stuff, unsigned> sum;
- for_each(basket.begin(), basket.end(), sum);
- return sum;
- }
-
- This isn't saying anything new, except that the STL defines containers and
- operations on containers in a generic way.
-
-
- >The usual thing is to write something like:
- >
- > Put_Line("done with sampling, W = " & Image(W)
- > & ", table = " & Image(Table));
- >
- >For simple data types, there is the 'Image attribute. For others, you
- >have to write your own Image function, which converts it to a string.
- >You said you wanted to do that anyway. If you don't like
- >Text_IO.Put_Line, write your own: Two procedures for each verbosity
- >level, and one of those two can add the new-line. Or maybe you always
- >want a new-line. Or maybe the verbosity should be passed as a
- >parameter, with a default. I can imagine many variations.
- >
- >Some people go even further, and define overloaded versions of "&" that
- >do both the concatenation and the conversion-to-string. Seems like
- >overkill to me, but some people like it.
-
- ===========
- I'd been bemoaning the lack of iostreams in Ada. Would you elaborate (no pun
- intended) more on how "&" and 'Image would be used? The common C++ idiom would
- be something like this:
-
- class Foo
- {
- ...
- public:
- ostream & Print(ostream &) const;
- };
- inline
- ostream & operator<<(ostream & os, const Foo & r)
- { return r.Print(os); }
-
- void Fred(const Foo & foo)
- {
- cout << "Done with sampling, " << foo << endl;
- }
-
- void Barney(const list<Foo> & foo, ostream & os)
- {
- os << "Done with sampling, " << foo.size() << " values:" << endl;
- ostream_iterator<Foo> outStream(os, "\n");
- copy(foo.begin(), foo.end(), outStream);
- os << endl;
- }
-
- >
- >You'll find a lot of anti-macro fanatics in the Ada world.
-
- =======
- Likewise in C++. :)
-
- >Macros are generally hard to understand for other reasons, I think.
-
- [... some worthy thoughts snipped ...]
- >
- >If you complain that you want macros to do For_Each, I'll answer by
- >giving you iterators, not by giving you macros. Same for Write_Sequence
- >-- better to use a procedure call than a macro call, IMHO.
-
- ============
- Yup. Good practice is not limited by choice of language, I see. :)
-
- The other sad part of function-like macros is safety of side-effects in macro
- arguments. Function arguments are evaluated once before calling; macros do god
- knows what. A canonical example of badness is:
-
- #define MatchChar(a,b) (putc(a==b?b:'_'))
- void foo()
- {
- MatchChar('X', getc());
- }
-
- If getc() were implemented as a macro, as it is on many systems, MatchChar
- would print the character following the one being matched. This may or may not
- be the desired result. Inline functions and templates generally make this a
- thing of the past.
-
- In spite of this, macros are still the only way to perform some useful tasks.
- For example:
-
- #ifndef _DEBUG
- #define assert(a)
- #else
- #define assert(a) {if (!a) {_assert_fail(__FILE__, __LINE__, #a);}}
- #endif
-
- How would you do this in Ada? In particular, how would I express pre- and
- post-conditions? The C macro grabs the filename and line number of the failure,
- and prints out verbatim the test condition that failed. __FILE__ and __LINE__
- are themselves macros, evaluated at the point where assert is invoked.
-
- Mike.
-
-